#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <math.h>
#include <stdlib.h>
#include <stdint.h>
#include <signal.h>
#include <dirent.h>
#include <string.h>
#include "lcd.h"
#include "bmp.h"
#include "touch.h"


int show_bmp(int x, int y, char *filename)
{

    // 打开图片
    int fd = open(filename, O_RDWR);
    if (fd == -1)
    {
        perror("open fb0 error"); // 打印错误信息
        return -1;
    }
    // 读取数据
    // 宽度
    int width = 0;
    lseek(fd, 0x12, SEEK_SET);
    read(fd, &width, 4);

    // 高度
    int height = 0;
    lseek(fd, 0x16, SEEK_SET);
    read(fd, &height, 4);

    // 色深
    short depth = 0;
    lseek(fd, 0x1C, SEEK_SET);
    read(fd, &depth, 2);

    int laizi = 0;     // 要填充的字节数
    int line_size = 0; // 实际的字节数

    laizi = 4 - (abs(width) * (depth / 8)) % 4;
    if (laizi == 4)
    {
        laizi = 0;
    }
    // 实际赖子数=有效赖子数+赖子
    line_size = abs(width) * (depth / 8) + laizi;
    // 一口气把所有像素点数据全部读取出来
    unsigned char buf[abs(height) * line_size];
    lseek(fd, 0x36, SEEK_SET);
    read(fd, buf, abs(height) * line_size);

    // 显示图片
    int color;
    unsigned char b, g, r, a = 0;
    int i, j;
    int num = 0;
    for (j = 0; j < abs(height); j++)
    {
        for (i = 0; i < abs(width); i++)
        {
            // 合成颜色数据
            b = buf[num++];
            g = buf[num++];
            r = buf[num++];
            if (depth == 32)
            {
                a = buf[num++];
            }
            color = (a << 24) | (r << 16) | (g << 8) | b;
            // 画点
            display_point((width > 0 ? i : abs(width) - 1 - i) + x, (height > 0 ? abs(height) - 1 - j : j) + y, color);
        }
        num = num + laizi; // 跳过无效的数据
    }
    // 关闭图片
    close(fd);
    return 0;
}

int circle_show_bmp(int x, int y, struct caixukun picture[])
{
    int i = 0, flag = -1;
    while (1)
    {
        flag = -1;
        show_bmp(x, y, picture[i].filename);
        //printf("%d\n",i);
        flag = get_touch();
        if (flag == 1)
        {
            i++;
            if (i == 3)
            {
                i = 0;
            }
        }
        if (flag == 0)
        {
            i--;
            if (i<0)
            {
                i = 2;
            }
        }
    }
}

//图片放缩
struct cor calculate_top_left_corner(int width, int height, float scale_x, float scale_y)
{
    struct cor result;

    // 计算目标缩放后的尺寸
    int dst_width = width * scale_x;
    int dst_height = height * scale_y;

    // 计算屏幕中心
    int screen_width = 800;
    int screen_height = 480;
    int screen_center_x = screen_width / 2;
    int screen_center_y = screen_height / 2;

    // 计算图像中心
    int image_center_x = dst_width / 2;
    int image_center_y = dst_height / 2;

    // 计算左上角坐标
    result.x = screen_center_x - image_center_x;
    result.y = screen_center_y - image_center_y;

    // 确保坐标不越界
    if (result.x < 0)
    {
        result.x = 0;
    }
    if (result.y < 0)
    {
        result.y = 0;
    }
    if (result.x + dst_width > screen_width)
    {
        result.x = screen_width - dst_width;
    }
    if (result.y + dst_height > screen_height)
    {
        result.y = screen_height - dst_height;
    }

    return result;
}


//显示放缩后的图片
int show_bmp_scaled(int x0, int y0, char *filename, float scale_x, float scale_y)

{
    int fd = open(filename, O_RDWR);
    if (fd == -1)
    {
        perror("OPEN ERROR");
        return -1;
    }

    int width = 0, height = 0;
    int depth = 0;
    if (lseek(fd, 0x12, SEEK_SET) == -1 || read(fd, &width, 4) != 4 || lseek(fd, 0x16, SEEK_SET) == -1 || read(fd, &height, 4) != 4 || lseek(fd, 0x1c, SEEK_SET) == -1 || read(fd, &depth, 4) != 4)
    {
        perror("Read ERROR");
        close(fd);
        return -1;
    }

    int laizi = 0;     // 表示要填充的字节数
    int line_size = 0; // 实际的字节数
    laizi = 4 - (abs(width) * (depth / 8)) % 4;
    if (laizi == 4)
    {
        laizi = 0;
    }

    line_size = abs(width) * (depth / 8) + laizi;
    unsigned char buf[abs(height) * line_size];
    if (lseek(fd, 0x36, SEEK_SET) == -1 || read(fd, buf, abs(height) * line_size) != abs(height) * line_size)
    {
        perror(" Read(1) ERROR");
        close(fd);
        return -1;
    }

    // 计算目标缩放后的尺寸
    int dst_width = abs(width) * scale_x;
    int dst_height = abs(height) * scale_y;

    unsigned b, g, r, a = 0;
    int src_i, src_j;
    int i, j;
    int num, src_num;
    int color;

    // 遍历缩放后的目标图像
    for (j = 0; j < dst_height; j++)
    {
        for (i = 0; i < dst_width; i++)
        {
            // 计算目标图像点对应的原始图像位置
            src_i = i / scale_x;
            // src_j = j / scale_y;
            src_j=(abs(height)-1)-(j/scale_y);//从底部开始

            // 计算原图像中的索引位置
            src_num = (src_j * line_size) + (src_i * (depth / 8));

            // 读取原图像中的颜色值
            b = buf[src_num++];
            g = buf[src_num++];
            r = buf[src_num++];
            if (depth == 32)
            {
                a = buf[src_num++];
            }
            color = (a << 24) | (r << 16) | (g << 8) | b;

            // 绘制目标点
            display_point(x0 + i, y0 + j, color);
        }
    }

    // 关闭图片文件
    close(fd);
    return 0;
}


#pragma pack(push, 1) // 按1字节对齐结构体
cai photo[20]; 
typedef struct {
    uint16_t bfType;         // 文件类型，必须是0x4D42
    uint32_t bfSize;         // 文件大小，包括文件头和像素数据
    uint16_t bfReserved1;    // 保留，必须是0
    uint16_t bfReserved2;    // 保留，必须是0
    uint32_t bfOffBits;      // 像素数据的偏移量
} BITMAPFILEHEADER;

typedef struct {
    uint32_t biSize;         // DIB 头大小
    int32_t  biWidth;        // 图像宽度
    int32_t  biHeight;       // 图像高度（正值表示从底部到顶部的像素）
    uint16_t biPlanes;       // 颜色平面数，必须是1
    uint16_t biBitCount;     // 每像素位数（24表示24位色，即RGB888）
    uint32_t biCompression;  // 压缩类型（0表示无压缩）
    uint32_t biSizeImage;    // 图像数据大小
    int32_t  biXPelsPerMeter; // 水平分辨率
    int32_t  biYPelsPerMeter; // 垂直分辨率
    uint32_t biClrUsed;      // 实际使用的颜色数（0表示所有颜色都使用）
    uint32_t biClrImportant; // 重要颜色数（0表示所有颜色都重要）
} BITMAPINFOHEADER;

#pragma pack(pop)
void write_bmp(const char *filename, const char *rgb888, int width, int height)
{
    FILE *file = fopen(filename, "wb");
    if (!file) {
        perror("fopen error");
        exit(1);
    }

    BITMAPFILEHEADER fileHeader;
    BITMAPINFOHEADER infoHeader;

    int row_padded = (width * 3 + 3) & (~3);
    int imageSize = row_padded * height;

    fileHeader.bfType = 0x4D42;
    fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + imageSize;
    fileHeader.bfReserved1 = 0;
    fileHeader.bfReserved2 = 0;
    fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    infoHeader.biSize = sizeof(BITMAPINFOHEADER);
    infoHeader.biWidth = width;
    infoHeader.biHeight = height;
    infoHeader.biPlanes = 1;
    infoHeader.biBitCount = 24;
    infoHeader.biCompression = 0;
    infoHeader.biSizeImage = imageSize;
    infoHeader.biXPelsPerMeter = 0;
    infoHeader.biYPelsPerMeter = 0;
    infoHeader.biClrUsed = 0;
    infoHeader.biClrImportant = 0;

    fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, file);
    fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, file);

    // Write pixel data with padding
    for (int i = 0; i < height; ++i) {
        fwrite(rgb888 + (width * 3 * (height - i - 1)), 3, width, file);
        uint8_t padding[3] = {0};
        fwrite(padding, (4 - (width * 3) % 4) % 4, 1, file);
    }

    fclose(file);
}
int is_bmp_file(const char *filename)
{
    size_t len = strlen(filename);
    return len >= 4 && strcmp(filename + len - 4, ".bmp") == 0;
}
int numsofAlbum()
{
    int nums = 0;
    DIR *dir;
    struct dirent *entry;
    struct stat file_stat;
    char filepath[256];  // 用于保存完整的文件路径

    // 打开目录
    dir = opendir("img");
    if (dir == NULL)
    {
        perror("opendir");
        exit(EXIT_FAILURE);
    }

    // 遍历目录
    while ((entry = readdir(dir)) != NULL)
    {
        // 拼接目录名和文件名，生成完整的文件路径
        snprintf(filepath, sizeof(filepath), "img/%s", entry->d_name);

        // 使用完整路径调用 stat
        if (stat(filepath, &file_stat) == -1)
        {
            perror("stat");
            continue;  // 如果 stat 失败，跳过当前文件
        }

        // 判断是否为文件且文件名以.bmp结尾
        if (S_ISREG(file_stat.st_mode) && is_bmp_file(entry->d_name))
        {
            cai p;
            // p.filename = entry->d_name;         
            strcpy(p.filename,entry->d_name)  ;
            //strcpy(photo[nums++], p);
            photo[nums++] = p;  // 统计有多少张图片 同时放进相册
        }
    }

    closedir(dir);
    return nums;
}



